package cn.shoptnt.consumer.shop.promotion;

import cn.shoptnt.client.promotion.PromotionScriptClient;
import cn.shoptnt.client.trade.PintuanClient;
import cn.shoptnt.consumer.core.event.PromotionScriptInitEvent;
import cn.shoptnt.framework.cache.Cache;
import cn.shoptnt.framework.context.ApplicationContextHolder;
import cn.shoptnt.framework.trigger.Interface.TimeTrigger;
import cn.shoptnt.framework.trigger.Interface.TimeTriggerExecuter;
import cn.shoptnt.framework.util.DateUtil;
import cn.shoptnt.model.base.CachePrefix;
import cn.shoptnt.model.base.message.PintuanChangeMsg;
import cn.shoptnt.model.base.message.PromotionScriptMsg;
import cn.shoptnt.model.base.rabbitmq.TimeExecute;
import cn.shoptnt.model.promotion.coupon.dos.CouponDO;
import cn.shoptnt.model.promotion.fulldiscount.dos.FullDiscountDO;
import cn.shoptnt.model.promotion.groupbuy.dos.GroupbuyActiveDO;
import cn.shoptnt.model.promotion.halfprice.dos.HalfPriceDO;
import cn.shoptnt.model.promotion.minus.dos.MinusDO;
import cn.shoptnt.model.promotion.pintuan.Pintuan;
import cn.shoptnt.model.promotion.seckill.dos.SeckillApplyDO;
import cn.shoptnt.model.promotion.seckill.dos.SeckillDO;
import cn.shoptnt.model.promotion.tool.enums.PromotionTypeEnum;
import cn.shoptnt.model.promotion.tool.enums.ScriptOperationTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 促销活动脚本初始化消费者
 * @author dmy
 * 2022-09-23
 */
@Component
public class PromotionScriptInitConsumer implements PromotionScriptInitEvent {

    @Autowired
    private PromotionScriptClient promotionScriptClient;

    @Autowired
    private TimeTrigger timeTrigger;

    @Autowired
    private PintuanClient pintuanClient;

    @Autowired
    private Cache cache;

    @Override
    public void scriptInit() {
        //先把所有缓存中的促销脚本信息删除掉
        deleteAllPromotionScriptCache();

        //1、初始化满减满赠、单品立减和第二件半价促销活动促销脚本信息
        initSellerPromotionScript();
        //2、初始化团购促销活动脚本信息
        initGroupbuyPromotionScript();
        //3、初始化限时抢购促销活动脚本信息
        initSeckillPromotionScript();
        //4、初始化拼团促销活动脚本信息
        initPintuanPromotionScript();
        //5、初始化优惠券脚本信息
        initCouponScript();
    }

    /**
     * 清除缓存所有促销脚本信息
     */
    private void deleteAllPromotionScriptCache() {
        //清除购物车级别缓存
        cache.vagueDel(CachePrefix.CART_PROMOTION.getPrefix());
        //清除sku级别缓存
        cache.vagueDel(CachePrefix.SKU_PROMOTION.getPrefix());
        //清除优惠券级别缓存
        cache.vagueDel(CachePrefix.COUPON_PROMOTION.getPrefix());
    }

    /**
     * 初始化优惠券促销脚本信息
     */
    private void initCouponScript() {
        List<CouponDO> couponDOS = this.promotionScriptClient.selectNoEndCoupon();
        if (couponDOS != null && couponDOS.size() != 0) {
            //获取生成团购促销活动的执行器
            TimeTriggerExecuter timeTriggerExecuter = (TimeTriggerExecuter) ApplicationContextHolder.getBean(TimeExecute.COUPON_SCRIPT_EXECUTER);
            for (CouponDO coupon : couponDOS) {
                PromotionScriptMsg promotionScriptMsg = new PromotionScriptMsg();
                promotionScriptMsg.setPromotionId(coupon.getCouponId());
                promotionScriptMsg.setPromotionName(coupon.getTitle());
                promotionScriptMsg.setPromotionType(PromotionTypeEnum.COUPON);
                promotionScriptMsg.setOperationType(ScriptOperationTypeEnum.CREATE);
                promotionScriptMsg.setEndTime(coupon.getEndTime());
                //如果活动开始时间大于当前时间，证明活动还没开始，需要创建生成脚本的延时任务执行器
                if (coupon.getStartTime() > DateUtil.getDateline()) {
                    String uniqueKey = "{TIME_TRIGGER_" + PromotionTypeEnum.COUPON.name() + "}_" + coupon.getCouponId();
                    timeTrigger.add(TimeExecute.COUPON_SCRIPT_EXECUTER, promotionScriptMsg, coupon.getStartTime(), uniqueKey);
                } else {
                    timeTriggerExecuter.execute(promotionScriptMsg);
                }
            }
        }
    }

    /**
     * 初始化拼团促销活动脚本信息
     */
    private void initPintuanPromotionScript() {
        List<Pintuan> pintuans = this.promotionScriptClient.selectNoEndPintuan();
        if (pintuans != null && pintuans.size() != 0) {
            for (Pintuan pintuan : pintuans) {
                //如果拼团活动还未开始，则设置拼团开始延时任务执行器
                if (pintuan.getStartTime() > DateUtil.getDateline()) {
                    //同时设置拼团结束的延时任务执行器
                    PintuanChangeMsg pintuanChangeMsg = new PintuanChangeMsg();
                    pintuanChangeMsg.setPintuanId(pintuan.getPromotionId());
                    pintuanChangeMsg.setOptionType(1);
                    timeTrigger.add(TimeExecute.PINTUAN_EXECUTER, pintuanChangeMsg, pintuan.getStartTime(), "{TIME_TRIGGER}_" + pintuan.getPromotionId());
                } else {
                    //如果拼团活动正在进行中，则直接开启拼团促销活动并创建促销活动脚本信息
                    this.pintuanClient.openPromotion(pintuan.getPromotionId());
                    //同时设置拼团结束的延时任务执行器
                    PintuanChangeMsg pintuanChangeMsg = new PintuanChangeMsg();
                    pintuanChangeMsg.setPintuanId(pintuan.getPromotionId());
                    pintuanChangeMsg.setOptionType(0);
                    timeTrigger.add(TimeExecute.PINTUAN_EXECUTER, pintuanChangeMsg, pintuan.getEndTime(), "{TIME_TRIGGER}_" + pintuan.getPromotionId());
                }
            }
        }
    }

    /**
     * 初始化限时抢购促销活动脚本信息
     */
    private void initSeckillPromotionScript() {
        List<SeckillDO> seckillDOS = this.promotionScriptClient.selectNoEndSeckill();
        if (seckillDOS != null && seckillDOS.size() != 0) {
            for (SeckillDO seckillDO : seckillDOS) {
                //获取当前参与限时抢购并且已经审核通过的商品信息
                List<SeckillApplyDO> seckillApplyDOS = this.promotionScriptClient.selectGoodsBySeckillId(seckillDO.getSeckillId());
                if (seckillApplyDOS == null || seckillApplyDOS.size() == 0) {
                    continue;
                }

                //给限时抢购商品生成促销脚本
                this.promotionScriptClient.createCacheScript(seckillDO.getSeckillId(), seckillApplyDOS);

                //还需要设置当前限时抢购结束是要触发的延时任务
                //启用延时任务,限时抢购促销活动结束时删除脚本信息
                PromotionScriptMsg promotionScriptMsg = new PromotionScriptMsg();
                promotionScriptMsg.setPromotionId(seckillDO.getSeckillId());
                promotionScriptMsg.setPromotionName(seckillDO.getSeckillName());
                promotionScriptMsg.setPromotionType(PromotionTypeEnum.SECKILL);
                promotionScriptMsg.setOperationType(ScriptOperationTypeEnum.DELETE);
                //获取限时抢购结束时间
                String date = DateUtil.toString(seckillDO.getStartDay(), "yyyy-MM-dd");
                long endTime = DateUtil.getDateline(date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
                promotionScriptMsg.setEndTime(endTime);

                String uniqueKey = "{TIME_TRIGGER_" + PromotionTypeEnum.SECKILL.name() + "}_" + seckillDO.getSeckillId();
                timeTrigger.add(TimeExecute.SECKILL_SCRIPT_EXECUTER, promotionScriptMsg, endTime, uniqueKey);
            }
        }
    }

    /**
     * 初始化团购促销活动脚本信息
     */
    private void initGroupbuyPromotionScript() {
        List<GroupbuyActiveDO> groupbuyActiveDOS = this.promotionScriptClient.selectNoEndGroupbuy();
        if (groupbuyActiveDOS != null && groupbuyActiveDOS.size() != 0) {
            //获取生成团购促销活动的执行器
            TimeTriggerExecuter timeTriggerExecuter = (TimeTriggerExecuter) ApplicationContextHolder.getBean(TimeExecute.GROUPBUY_SCRIPT_EXECUTER);
            for (GroupbuyActiveDO groupbuyActiveDO : groupbuyActiveDOS) {
                PromotionScriptMsg promotionScriptMsg = new PromotionScriptMsg();
                promotionScriptMsg.setPromotionId(groupbuyActiveDO.getActId());
                promotionScriptMsg.setPromotionName(groupbuyActiveDO.getActName());
                promotionScriptMsg.setPromotionType(PromotionTypeEnum.GROUPBUY);
                promotionScriptMsg.setOperationType(ScriptOperationTypeEnum.CREATE);
                promotionScriptMsg.setEndTime(groupbuyActiveDO.getEndTime());
                //如果活动开始时间大于当前时间，证明活动还没开始，需要创建生成脚本的延时任务执行器
                if (groupbuyActiveDO.getStartTime() > DateUtil.getDateline()) {
                    String uniqueKey = "{TIME_TRIGGER_" + PromotionTypeEnum.GROUPBUY.name() + "}_" + groupbuyActiveDO.getActId();
                    timeTrigger.add(TimeExecute.GROUPBUY_SCRIPT_EXECUTER, promotionScriptMsg, groupbuyActiveDO.getStartTime(), uniqueKey);
                } else {
                    timeTriggerExecuter.execute(promotionScriptMsg);
                }
            }
        }
    }

    /**
     * 初始化商品发布的促销活动脚本信息
     * 主要包含：满减满赠、单品立减和第二件半价促销活动
     */
    private void initSellerPromotionScript() {
        //获取生成满减促销活动的执行器
        TimeTriggerExecuter timeTriggerExecuter = (TimeTriggerExecuter) ApplicationContextHolder.getBean(TimeExecute.SELLER_PROMOTION_SCRIPT_EXECUTER);
        //获取当前时间
        long nowTime = DateUtil.getDateline();
        //获取当前正在进行和未开始的满减促销活动信息
        List<FullDiscountDO> fullDiscountDOS = this.promotionScriptClient.selectNoEndFullDiscount();
        if (fullDiscountDOS != null && fullDiscountDOS.size() != 0) {
            for (FullDiscountDO fullDiscountDO : fullDiscountDOS) {
                PromotionScriptMsg promotionScriptMsg = new PromotionScriptMsg();
                promotionScriptMsg.setPromotionId(fullDiscountDO.getFdId());
                promotionScriptMsg.setPromotionName(fullDiscountDO.getTitle());
                promotionScriptMsg.setPromotionType(PromotionTypeEnum.FULL_DISCOUNT);
                promotionScriptMsg.setOperationType(ScriptOperationTypeEnum.CREATE);
                promotionScriptMsg.setEndTime(fullDiscountDO.getEndTime());
                //如果活动开始时间大于当前时间，证明活动还没开始，需要创建生成脚本的延时任务执行器
                if (fullDiscountDO.getStartTime() > nowTime) {
                    String uniqueKey = "{TIME_TRIGGER_" + PromotionTypeEnum.FULL_DISCOUNT.name() + "}_" + fullDiscountDO.getFdId();
                    timeTrigger.add(TimeExecute.SELLER_PROMOTION_SCRIPT_EXECUTER, promotionScriptMsg, fullDiscountDO.getStartTime(), uniqueKey);
                } else {
                    timeTriggerExecuter.execute(promotionScriptMsg);
                }
            }
        }
        //获取当前正在进行和未开始的单品立减促销活动
        List<MinusDO> minusDOS = this.promotionScriptClient.selectNoEndMinus();
        if (minusDOS != null && minusDOS.size() != 0) {
            for (MinusDO minusDO : minusDOS) {
                PromotionScriptMsg promotionScriptMsg = new PromotionScriptMsg();
                promotionScriptMsg.setPromotionId(minusDO.getMinusId());
                promotionScriptMsg.setPromotionName(minusDO.getTitle());
                promotionScriptMsg.setPromotionType(PromotionTypeEnum.MINUS);
                promotionScriptMsg.setOperationType(ScriptOperationTypeEnum.CREATE);
                promotionScriptMsg.setEndTime(minusDO.getEndTime());
                //如果活动开始时间大于当前时间，证明活动还没开始，需要创建生成脚本的延时任务执行器
                if (minusDO.getStartTime() > nowTime) {
                    String uniqueKey = "{TIME_TRIGGER_" + PromotionTypeEnum.MINUS.name() + "}_" + minusDO.getMinusId();
                    timeTrigger.add(TimeExecute.SELLER_PROMOTION_SCRIPT_EXECUTER, promotionScriptMsg, minusDO.getStartTime(), uniqueKey);
                } else {
                    timeTriggerExecuter.execute(promotionScriptMsg);
                }
            }
        }
        //获取当前正在进行和未开始的第二件半价促销活动
        List<HalfPriceDO> halfPriceDOS = this.promotionScriptClient.selectNoEndHalfPrice();
        if (halfPriceDOS != null && halfPriceDOS.size() != 0) {
            for (HalfPriceDO halfPriceDO : halfPriceDOS) {
                PromotionScriptMsg promotionScriptMsg = new PromotionScriptMsg();
                promotionScriptMsg.setPromotionId(halfPriceDO.getHpId());
                promotionScriptMsg.setPromotionName(halfPriceDO.getTitle());
                promotionScriptMsg.setPromotionType(PromotionTypeEnum.HALF_PRICE);
                promotionScriptMsg.setOperationType(ScriptOperationTypeEnum.CREATE);
                promotionScriptMsg.setEndTime(halfPriceDO.getEndTime());
                //如果活动开始时间大于当前时间，证明活动还没开始，需要创建生成脚本的延时任务执行器
                if (halfPriceDO.getStartTime() > nowTime) {
                    String uniqueKey = "{TIME_TRIGGER_" + PromotionTypeEnum.HALF_PRICE.name() + "}_" + halfPriceDO.getHpId();
                    timeTrigger.add(TimeExecute.SELLER_PROMOTION_SCRIPT_EXECUTER, promotionScriptMsg, halfPriceDO.getStartTime(), uniqueKey);
                } else {
                    timeTriggerExecuter.execute(promotionScriptMsg);
                }
            }
        }
    }
}
